home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / shells / scsh-0.4 / scsh-0 / scsh-0.4.2 / bcomp / syntax.scm < prev    next >
Text File  |  1995-10-13  |  24KB  |  826 lines

  1. ; Copyright (c) 1993, 1994 Richard Kelsey and Jonathan Rees.  See file COPYING.
  2.  
  3. ; Syntactic stuff: transforms and operators.
  4.  
  5.  
  6. (define usual-operator-type
  7.   (procedure-type any-arguments-type value-type #f))
  8.  
  9. ; --------------------
  10. ; Operators (= special operators and primitives)
  11.  
  12. (define-record-type operator :operator
  13.   (make-operator type nargs uid name)
  14.   operator?
  15.   (type operator-type set-operator-type!)
  16.   (nargs operator-nargs)
  17.   (uid operator-uid)
  18.   (name operator-name))
  19.  
  20. (define-record-discloser :operator
  21.   (lambda (s)
  22.     (list 'operator
  23.       (operator-name s)
  24.       (type->sexp (operator-type s) #t))))
  25.  
  26. (define (get-operator name . type-option)
  27.   (let ((type (if (null? type-option) #f (car type-option)))
  28.     (probe (table-ref operators-table name)))
  29.     (if (operator? probe)
  30.     (let ((previous-type (operator-type probe)))
  31.       (cond ((not type))
  32.         ((symbol? type)        ; 'leaf or 'internal
  33.          (if (not (eq? type previous-type))
  34.              (warn "operator type inconsistency" name type previous-type)))
  35.         ((subtype? type previous-type)  ;Improvement
  36.          (set-operator-type! probe type))
  37.         ((not (subtype? previous-type type))
  38.          (warn "operator type inconsistency"
  39.                name
  40.                (type->sexp previous-type 'foo)
  41.                (type->sexp type 'foo))))
  42.       probe)
  43.     (let* ((uid *operator-uid*)
  44.            (type (or type usual-operator-type))
  45.            (op (make-operator type
  46.                   (if (and (not (symbol? type))
  47.                        (fixed-arity-procedure-type? type))
  48.                       (procedure-type-arity type)
  49.                       #f)
  50.                   uid
  51.                   name)))
  52.       (if (>= uid number-of-operators)
  53.           (warn "too many operators" (operator-name op) (operator-type op)))
  54.       (set! *operator-uid* (+ *operator-uid* 1))
  55.       (table-set! operators-table (operator-name op) op)
  56.       (vector-set! the-operators uid op)
  57.       op))))
  58.  
  59. (define *operator-uid* 0)
  60.  
  61. (define operators-table (make-table))
  62.  
  63. (define number-of-operators 200)  ;Fixed-size limits bad, but speed good
  64. (define the-operators (make-vector number-of-operators #f))
  65.  
  66. ; --------------------
  67. ; Operator tables (for fast dispatch)
  68.  
  69. (define (make-operator-table default . mumble-option)
  70.   (let ((v (make-vector number-of-operators default)))
  71.     (if (not (null? mumble-option))
  72.     (define-usual-suspects v (car mumble-option)))
  73.     v))
  74.  
  75. (define operator-table-ref vector-ref)
  76.  
  77. (define (operator-lookup table op)
  78.   (operator-table-ref table (operator-uid op)))
  79.  
  80. (define (operator-define! table name proc-or-type . proc-option)
  81.   (if (null? proc-option)
  82.       (vector-set! table        ;Obsolescent
  83.            (operator-uid (if (pair? name)
  84.                      (get-operator (car name) (cadr name))
  85.                      (get-operator name)))
  86.            proc-or-type)
  87.       (vector-set! table
  88.            (operator-uid (get-operator name proc-or-type))
  89.            (car proc-option))))
  90.  
  91. ; --------------------
  92. ; Nodes
  93.  
  94. ; A node is an annotated expression (or definition or other form).
  95. ; The FORM component of a node is an S-expression of the same form as
  96. ; the S-expression representation of the expression.  E.g. for
  97. ; literals, the form is the literal value; for variables the form is
  98. ; the variable name; for IF expressions the form is a 4-element list
  99. ; (ignored test con alt).  Nodes also have a tag identifying what kind
  100. ; of node it is (literal, variable, if, etc.) and a property list.
  101.  
  102. (define-record-type node :node
  103.   (really-make-node uid form plist)
  104.   node?
  105.   (uid node-operator-id)
  106.   (form node-form)
  107.   (plist node-plist set-node-plist!))
  108.  
  109. (define-record-discloser :node
  110.   (lambda (n) (list (operator-name (node-operator n)) (node-form n))))
  111.  
  112. (define (make-node operator form)
  113.   (really-make-node (operator-uid operator) form '()))
  114.  
  115. (define (node-ref node key)
  116.   (let ((probe (assq key (node-plist node))))
  117.     (if probe (cdr probe) #f)))
  118.  
  119. (define (node-set! node key value) ;gross
  120.   (if value
  121.       (let ((probe (assq key (node-plist node))))
  122.     (if probe
  123.         (set-cdr! probe value)
  124.         (set-node-plist! node (cons (cons key value) (node-plist node)))))
  125.       (let loop ((l (node-plist node)) (prev #f))
  126.     (cond ((null? l) 'lose)
  127.           ((eq? key (caar l))
  128.            (if prev
  129.            (set-cdr! prev (cdr l))
  130.            (set-node-plist! node (cdr l))))
  131.           (else (loop (cdr l) l))))))
  132.  
  133. (define (node-operator node)
  134.   (vector-ref the-operators (node-operator-id node)))
  135.  
  136.  
  137. (define (node-predicate name . type-option)
  138.   (let ((id (operator-uid (apply get-operator name type-option))))
  139.     (lambda (node)
  140.       (= (node-operator-id node) id))))
  141.  
  142. (define (make-similar-node node form)
  143.   (if (equal? form (node-form node))
  144.       node
  145.       (make-node (node-operator node) form)))
  146.  
  147. ; --------------------
  148. ; Generated names
  149.  
  150. ; Generated names make lexically-scoped macros work.  They're the same
  151. ; as what Alan Bawden and Chris Hanson call "aliases".  The parent
  152. ; field is always another name (perhaps generated).  The parent chain
  153. ; provides an access path to the name's binding, should one ever be
  154. ; needed.  That is: If name M is bound to a transform T that generates
  155. ; name G as an alias for name N, then M is (generated-parent-name G),
  156. ; so we can get the binding of G by accessing the binding of N in T's
  157. ; environment of closure, and we get T by looking up M in the
  158. ; environment in which M is *used*.
  159.  
  160. (define-record-type generated :generated
  161.   (make-generated symbol token env parent-name)
  162.   generated?
  163.   (symbol      generated-symbol)
  164.   (token       generated-token)
  165.   (env           generated-env)
  166.   (parent-name generated-parent-name))
  167.  
  168. (define-record-discloser :generated
  169.   (lambda (name)
  170.     (list 'generated (generated-symbol name) (generated-uid name))))
  171.  
  172. (define (generate-name symbol env parent-name)    ;for opt/inline.scm
  173.   (make-generated symbol (cons #f #f) env parent-name)) ;foo
  174.  
  175. (define (generated-uid g)
  176.   (let ((t (generated-token g)))
  177.     (or (car t)
  178.     (let ((uid *generated-uid*))
  179.       (set! *generated-uid* (+ *generated-uid* 1))
  180.       (set-car! t uid)
  181.       uid))))
  182.  
  183. (define *generated-uid* 0)
  184.  
  185. (define (name->symbol name)
  186.   (if (symbol? name)
  187.       name
  188.       (string->symbol (string-append (symbol->string (generated-symbol name))
  189.                      "##"
  190.                      (number->string (generated-uid name))))))
  191.  
  192. (define (name-hash name)
  193.   (cond ((symbol? name)
  194.      (string-hash (symbol->string name)))
  195.     ((generated? name)
  196.      (name-hash (generated-symbol name)))
  197.     (else (error "invalid name" name))))
  198.  
  199.  
  200. ; Used by QUOTE to turn generated names back into symbols
  201.  
  202. (define (desyntaxify thing)
  203.   (cond ((or (boolean? thing) (null? thing) (number? thing)
  204.          (symbol? thing) (char? thing))
  205.      thing)
  206.     ((string? thing)
  207.      (make-immutable! thing))
  208.     ((generated? thing) (desyntaxify (generated-symbol thing)))
  209.     ((pair? thing)
  210.      (make-immutable!
  211.       (let ((x (desyntaxify (car thing)))
  212.         (y (desyntaxify (cdr thing))))
  213.         (if (and (eq? x (car thing))
  214.              (eq? y (cdr thing)))
  215.         thing
  216.         (cons x y)))))
  217.     ((vector? thing)
  218.      (make-immutable!
  219.       (let ((new (make-vector (vector-length thing) #f)))
  220.         (let loop ((i 0) (same? #t))
  221.           (if (>= i (vector-length thing))
  222.           (if same? thing new)
  223.           (let ((x (desyntaxify (vector-ref thing i))))
  224.             (vector-set! new i x)
  225.             (loop (+ i 1)
  226.               (and same? (eq? x (vector-ref thing i))))))))))
  227.     ((operator? thing)
  228.      (warn "operator in quotation" thing)
  229.      (operator-name thing))  ;Foo
  230.     (else
  231.      (warn "invalid datum in quotation" thing)
  232.      thing)))
  233.  
  234. ; --------------------
  235. ; Transforms
  236.  
  237. ; A transform represents a source-to-source rewrite rule: either a
  238. ; macro or an in-line procedure.
  239.  
  240. (define-record-type transform :transform
  241.   (really-make-transform xformer env type aux-names source id)
  242.   transform?
  243.   (xformer   transform-procedure)
  244.   (env         transform-env)
  245.   (type         transform-type)
  246.   (aux-names transform-aux-names)
  247.   (source    transform-source)    ;for reification
  248.   (id         transform-id))
  249.  
  250. (define (make-transform thing env type source id)
  251.   (let ((type (if (or (pair? type) (symbol? type))
  252.           (sexp->type type #t)
  253.           type)))
  254.     (make-immutable!
  255.      (if (pair? thing)
  256.      (really-make-transform (car thing) env type (cdr thing) source id)
  257.      (really-make-transform thing env type #f source id)))))
  258.  
  259. (define-record-discloser :transform
  260.   (lambda (m) (list 'transform (transform-id m))))
  261.  
  262. (define (maybe-transform t exp env-of-use)
  263.   (let* ((token (cons #f #f))
  264.      (new-env (bind-aliases token t env-of-use))
  265.      (rename (make-name-generator (transform-env t)
  266.                       token
  267.                       (node-form (car exp))))
  268.      (compare
  269.       (lambda (name1 name2)
  270.         (or (eqv? name1 name2)
  271.         (and (name? name1)
  272.              (name? name2)
  273.              (same-denotation? (lookup new-env name1)
  274.                        (lookup new-env name2)))))))
  275.     (values ((transform-procedure t) exp rename compare)
  276.         new-env
  277.         token)))
  278.  
  279. (define (bind-aliases token t env-of-use)
  280.   (let ((env-of-definition (transform-env t)))
  281.     (if (procedure? env-of-definition)
  282.     (lambda (name)
  283.       (if (and (generated? name)
  284.            (eq? (generated-token name) token))
  285.           (lookup env-of-definition (generated-symbol name))
  286.           (lookup env-of-use name)))
  287.     env-of-use)))  ;Lose
  288.  
  289. (define (make-name-generator env token parent-name)
  290.   (let ((alist '()))            ;list of (symbol . generated)
  291.     (lambda (symbol)
  292.       (if (symbol? symbol)
  293.       (let ((probe (assq symbol alist)))
  294.         (if probe
  295.         (cdr probe)
  296.         (let ((new-name (make-generated symbol token env parent-name)))
  297.           (set! alist (cons (cons symbol new-name)
  298.                     alist))
  299.           new-name)))
  300.       (error "non-symbol argument to rename procedure"
  301.          symbol parent-name)))))
  302.  
  303. (define (same-denotation? x y)
  304.   (or (equal? x y)
  305.       (and (binding? x)
  306.        (binding? y)
  307.        (eq? (binding-place x) (binding-place y)))))
  308.  
  309.  
  310. ; --------------------
  311. ; Bindings: the things that are usually returned by LOOKUP.
  312.  
  313. ; Representation is #(type place operator-or-transform-or-#f).
  314. ; For top-level bindings, place is usually a location.
  315.  
  316. (define binding? vector?)
  317. (define (binding-type b) (vector-ref b 0))
  318. (define (binding-place b) (vector-ref b 1))
  319. (define (binding-static b) (vector-ref b 2))
  320.  
  321. (define (set-binding-place! b place) (vector-set! b 1 place))
  322.  
  323. (define (make-binding type place static)
  324.   (let ((b (make-vector 3 place)))
  325.     (vector-set! b 0 type)
  326.     (vector-set! b 2 static)
  327.     b))
  328.  
  329. (define (clobber-binding! b type place static)
  330.   (vector-set! b 0 type)
  331.   (if place
  332.       (set-binding-place! b place))
  333.   (vector-set! b 2 static))
  334.  
  335. ; Return a binding that's similar to the given one, but has its type
  336. ; replaced with the given type.
  337.  
  338. (define (impose-type type b integrate?)
  339.   (if (or (eq? type syntax-type)
  340.       (not (binding? b)))
  341.       b
  342.       (make-binding (if (eq? type undeclared-type)
  343.             (let ((type (binding-type b)))
  344.               (if (variable-type? type)
  345.                   (variable-value-type type)
  346.                   type))
  347.             type)
  348.             (binding-place b)
  349.             (if integrate?
  350.             (binding-static b)
  351.             #f))))
  352.  
  353. ; Return a binding that's similar to the given one, but has any
  354. ; procedure integration or other unnecesary static information
  355. ; removed.  But don't remove static information for macros (or
  356. ; structures, interfaces, etc.)
  357.  
  358. (define (forget-integration b)
  359.   (if (and (binding-static b)
  360.        (subtype? (binding-type b) any-values-type))
  361.       (make-binding (binding-type b)
  362.             (binding-place b)
  363.             #f)
  364.       b))
  365.  
  366. ; --------------------
  367. ; Expression classifier.  Returns a node.
  368.  
  369. (define (classify form env)
  370.   (cond ((node? form)
  371.      (if (and (name-node? form)
  372.           (not (node-ref form 'binding)))
  373.          (classify-name (node-form form) env)
  374.          form))
  375.     ((name? form)
  376.      (classify-name form env))
  377.         ((pair? form)
  378.      (let ((op-node (classify (car form) env)))
  379.        (if (name-node? op-node)
  380.            (let ((probe (node-ref op-node 'binding)))
  381.          (if (binding? probe)
  382.              (let ((s (binding-static probe)))
  383.                (cond ((operator? s)
  384.                   (classify-operator-form s op-node form env))
  385.                  ((and (transform? s)
  386.                    (eq? (binding-type probe) syntax-type))
  387.                   ;; Non-syntax transforms (i.e. procedure
  388.                   ;; integrations) get done by MAYBE-TRANSFORM-CALL.
  389.                   (classify-macro-application
  390.                            s (cons op-node (cdr form)) env))
  391.                  (else
  392.                   (classify-call op-node form env))))
  393.              (classify-call op-node form env)))
  394.            (classify-call op-node form env))))
  395.     ((literal? form)
  396.      (classify-literal form))
  397.     ;; ((qualified? form) ...)
  398.     (else
  399.      (classify (syntax-error "invalid expression" form) env))))
  400.  
  401. (define call-node? (node-predicate 'call 'internal))
  402. (define name-node? (node-predicate 'name 'leaf))
  403.  
  404. (define classify-literal
  405.   (let ((op (get-operator 'literal 'leaf)))
  406.     (lambda (exp)
  407.       (make-node op exp))))
  408.  
  409. (define classify-call
  410.   (let ((operator/call (get-operator 'call 'internal)))
  411.     (lambda (proc-node exp env)
  412.       (make-node operator/call
  413.          (if (eq? proc-node (car exp))
  414.              exp        ;+++
  415.              (cons proc-node (cdr exp)))))))
  416.  
  417. ; An environment is a procedure that takes a name and returns one of
  418. ; the following:
  419. ;
  420. ;  1. A binding record.
  421. ;  2. A node, which is taken to be a substitution for the name.
  422. ;  3. Another name, meaning that the first name is unbound.  The name
  423. ;     returned will be a symbol even if the original name was generated.
  424. ;
  425. ; In case 1, CLASSIFY caches the binding as the node's BINDING property.
  426. ; In case 2, it simply returns the node.
  427.  
  428. (define (classify-name name env)
  429.   (let ((binding (lookup env name)))
  430.     (if (node? binding)
  431.     binding
  432.     (let ((node (make-node operator/name name)))
  433.       (if (not (unbound? binding))
  434.           (node-set! node 'binding binding))
  435.       node))))
  436.  
  437. (define operator/name (get-operator 'name 'leaf))
  438.  
  439. ; Expand a macro or in-line procedure application.
  440.  
  441. (define (classify-macro-application t form env-of-use)
  442.   (classify-transform-application
  443.        t form env-of-use
  444.        (lambda () 
  445.      (classify (syntax-error "use of macro doesn't match definition"
  446.                  (cons (schemify (car form) env-of-use)
  447.                        (desyntaxify (cdr form))))
  448.            env-of-use))))
  449.  
  450.  
  451. (define classify-transform-application
  452.   (let ((operator/with-aliases (get-operator 'with-aliases syntax-type)))
  453.     (lambda (t form env-of-use lose)
  454.       (call-with-values (lambda () (maybe-transform t form env-of-use))
  455.     (lambda (new-form new-env token)
  456.       (cond ((eq? new-form form)
  457.          (lose))
  458.         ((eq? new-env env-of-use)
  459.          (classify new-form new-env))
  460.         (else
  461.          (make-node operator/with-aliases
  462.                 `(with-aliases ,(car form)
  463.                        ,token
  464.                        ,new-form)))))))))
  465.  
  466. (define (maybe-transform-call proc-node node env)
  467.   (if (name-node? proc-node)
  468.       (let ((b (or (node-ref proc-node 'binding)
  469.            (lookup env (node-form proc-node)))))
  470.     (if (binding? b)
  471.         (let ((s (binding-static b)))
  472.           (cond ((transform? s)
  473.              (classify-transform-application s
  474.                              (node-form node)
  475.                              env
  476.                              (lambda () node)))
  477.             ;; ((operator? s) (make-node s (node-form node)))
  478.             (else node)))
  479.         node))
  480.       node))
  481.  
  482.  
  483. ; --------------------
  484. ; Specialist classifiers for particular operators
  485.  
  486. (define (classify-operator-form op op-node form env)
  487.   ((operator-table-ref classifiers (operator-uid op))
  488.    op op-node form env))
  489.  
  490. (define classifiers
  491.   (make-operator-table (lambda (op op-node form env)
  492.              (if (let ((nargs (operator-nargs op)))
  493.                    (or (not nargs)
  494.                    (= nargs (length (cdr form)))))
  495.                  (make-node op (cons op-node (cdr form)))
  496.                  (classify-call op-node form env)))))
  497.  
  498. (define (define-classifier name proc)
  499.   (operator-define! classifiers name syntax-type proc))
  500.  
  501. ; Remove generated names from quotations.
  502.  
  503. (define-classifier 'quote
  504.   (lambda (op op-node exp env)
  505.     (make-node op (list op-node (desyntaxify (cadr exp))))))
  506.  
  507. ; Convert one-armed IF to two-armed IF.
  508.  
  509. (define-classifier 'if
  510.   (lambda (op op-node exp env)
  511.     (make-node op
  512.            (cons op-node
  513.              (if (null? (cdddr exp))
  514.              (append (cdr exp) (list (unspecific-node)))
  515.              (cdr exp))))))
  516.  
  517. (define unspecific-node
  518.   (let ((op (get-operator 'unspecific
  519.               (proc () unspecific-type))))
  520.     (lambda ()
  521.       (make-node op '(unspecific)))))
  522.  
  523. ; Rewrite (define (name . vars) body ...)
  524. ;  as (define foo (lambda vars body ...)).
  525.  
  526. (define-classifier 'define
  527.   (let ((operator/lambda (get-operator 'lambda syntax-type))
  528.     (operator/unassigned (get-operator 'unassigned 
  529.                        (proc () value-type)))) ;foo
  530.     (lambda (op op-node form env)
  531.       (let ((pat (cadr form)))
  532.     (make-node op
  533.            (cons op-node
  534.              (if (pair? pat)
  535.                  (list (car pat)
  536.                    (make-node operator/lambda
  537.                           `(lambda ,(cdr pat)
  538.                          ,@(cddr form))))
  539.                  (list pat
  540.                    (if (null? (cddr form))
  541.                        (make-node operator/unassigned
  542.                           `(unassigned))
  543.                        (caddr form))))))))))
  544.  
  545. ;(define (make-define-node op op-node lhs rhs)
  546. ;  (make-node op (list op-node lhs rhs)))
  547.  
  548. (define define-node? (node-predicate 'define))
  549. (define define-syntax-node? (node-predicate 'define-syntax syntax-type))
  550.  
  551.  
  552. ; For the module system:
  553.  
  554. (define-classifier 'structure-ref
  555.   (lambda (op op-node form env)
  556.     (let ((struct-node (classify (cadr form) env))
  557.       (lose (lambda ()
  558.           (classify (syntax-error "invalid structure reference" form)
  559.                 env))))
  560.       (if (and (name? (caddr form))
  561.            (name-node? struct-node))
  562.       (let ((b (node-ref struct-node 'binding)))
  563.         (if (and (binding? b) (binding-static b)) ; (structure? ...)
  564.         (classify (generate-name (desyntaxify (caddr form))
  565.                      (binding-static b)
  566.                      (node-form struct-node))
  567.               env)
  568.         (lose)))
  569.       (lose)))))
  570.  
  571. ; Magical Scheme 48 internal thing, mainly for use by the
  572. ; DEFINE-PACKAGE macro.
  573.  
  574. (define-classifier '%file-name%
  575.   (let ((operator/quote (get-operator 'quote syntax-type)))
  576.     (lambda (op op-node form env)
  577.       (make-node operator/quote `',(get-funny env funny-name/source-file-name)))))
  578.  
  579. (define funny-name/source-file-name
  580.   (string->symbol ".source-file-name."))
  581.  
  582. (define (bind-source-file-name filename env)
  583.   (if filename
  584.       (bind1 funny-name/source-file-name
  585.          (make-binding syntax-type #f filename)
  586.          env)
  587.       env))
  588.  
  589.  
  590. ; To do:
  591. ;  Check syntax of others special forms
  592.  
  593. ; --------------------
  594. ; Environments
  595.  
  596. (define (lookup env name)
  597.   (env name))
  598.  
  599. (define (bind1 name binding env)
  600.   (lambda (a-name)
  601.     (if (eq? a-name name)
  602.     binding
  603.     (lookup env a-name))))
  604.  
  605. ; corollary
  606.  
  607. (define (bind names bindings env)
  608.   (cond ((null? names) env)
  609.     (else
  610.      (bind1 (car names)
  611.         (car bindings)
  612.         (bind (cdr names) (cdr bindings) env)))))
  613.  
  614. (define (bindrec names env->bindings env)
  615.   (set! env (bind names
  616.           (env->bindings (lambda (a-name) (env a-name)))
  617.           env))
  618.   env)
  619.  
  620.  
  621. ; --------------------
  622. ; Utilities
  623.  
  624. (define (literal? exp)
  625.   (or (number? exp) (char? exp) (string? exp) (boolean? exp)))
  626.  
  627. (define (number-of-required-args formals)
  628.   (do ((l formals (cdr l))
  629.        (i 0 (+ i 1)))
  630.       ((not (pair? l)) i)))
  631.  
  632. (define (n-ary? formals)
  633.   (cond ((null? formals) #f)
  634.     ((pair? formals) (n-ary? (cdr formals)))
  635.     (else #t)))
  636.  
  637. (define (normalize-formals formals)
  638.   (cond ((null? formals) '())
  639.         ((pair? formals)
  640.      (cons (car formals) (normalize-formals (cdr formals))))
  641.         (else (list formals))))
  642.  
  643.  
  644. (define (syntax? d)
  645.   (cond ((operator? d)
  646.      (eq? (operator-type d) syntax-type))
  647.     ((transform? d)
  648.      (eq? (transform-type d) syntax-type))
  649.     (else #f)))
  650.  
  651. (define (name? thing)
  652.   (or (symbol? thing)
  653.       (generated? thing)))
  654.  
  655. (define unbound? name?)
  656.  
  657.  
  658. ; --------------------
  659. ; LET-SYNTAX and friends
  660.  
  661. (define (define-usual-suspects table mumble)
  662.  
  663.   (operator-define! table 'let-syntax syntax-type
  664.     (mumble (lambda (node env)
  665.           (let* ((form (node-form node))
  666.              (specs (cadr form)))
  667.         (values (caddr form)
  668.             (bind (map car specs)
  669.                   (map (lambda (spec)
  670.                      (make-binding syntax-type
  671.                            (list 'let-syntax)
  672.                            (process-syntax (cadr spec)
  673.                                    env
  674.                                    (car spec)
  675.                                    env)))
  676.                    specs)
  677.                   env))))))
  678.  
  679.   (operator-define! table 'letrec-syntax syntax-type
  680.     (mumble (lambda (node env)
  681.           (let* ((form (node-form node))
  682.              (specs (cadr form)))
  683.         (values (caddr form)
  684.             (bindrec (map car specs)
  685.                  (lambda (new-env)
  686.                    (map (lambda (spec)
  687.                       (make-binding
  688.                          syntax-type
  689.                          (list 'letrec-syntax)
  690.                          (process-syntax (cadr spec)
  691.                                  new-env
  692.                                  (car spec)
  693.                                  new-env)))
  694.                     specs))
  695.                  env))))))
  696.  
  697.   (operator-define! table 'with-aliases syntax-type
  698.     (mumble (lambda (node env)
  699.           (let ((form (node-form node)))
  700.         (values (cadddr form)
  701.             (bind-aliases (caddr form)
  702.                       (binding-static
  703.                            (node-ref (cadr form) 'binding))
  704.                       env)))))))
  705.  
  706. (define (process-syntax form env name env-or-whatever)
  707.   (let ((eval+env (force (reflective-tower env))))
  708.     (make-transform ((car eval+env) form (cdr eval+env))
  709.             env-or-whatever syntax-type form name)))
  710.  
  711. (define (get-funny env name)
  712.   (let ((binding (lookup env name)))
  713.     (if (binding? binding)
  714.     (binding-static binding)
  715.     #f)))
  716.  
  717. ; An environment's "reflective tower" is a promise that is expected to
  718. ; deliver, when forced, a pair (eval . env).
  719.  
  720. (define funny-name/reflective-tower
  721.   (string->symbol ".reflective-tower."))
  722.  
  723. (define (reflective-tower env)
  724.   (or (get-funny env funny-name/reflective-tower)
  725.       (error "environment has no environment for syntax" env)))
  726.  
  727.  
  728. ; --------------------
  729. ; The horror of internal defines
  730.  
  731. ; The continuation argument to SCAN-BODY takes two arguments: a list
  732. ; of definition nodes, and a list of other things (nodes and
  733. ; expressions).
  734.  
  735. (define (scan-body forms env cont)
  736.   (if (or (null? forms)
  737.       (null? (cdr forms)))
  738.       (cont '() forms)            ;+++ tiny compiler speedup?
  739.       (scan-body-forms forms env '()
  740.                (lambda (defs exps env)
  741.              (cont defs exps)))))
  742.  
  743. (define (scan-body-forms forms env defs cont)
  744.   (if (null? forms)
  745.       (cont defs '() env)
  746.       (let ((node (classify (car forms) env))
  747.         (forms (cdr forms)))
  748.     (cond ((define-node? node)
  749.            (scan-body-forms forms
  750.                 (let ((name (cadr (node-form node))))
  751.                   (bind1 name
  752.                      ;; Shadow, and don't cache lookup
  753.                      (make-node operator/name name)
  754.                      env))
  755.                 (cons node defs)
  756.                 cont))
  757.           ((begin-node? node)
  758.            (scan-body-forms (cdr (node-form node))
  759.                 env
  760.                 defs
  761.                 (lambda (new-defs exps env)
  762.                   (cond ((null? exps)
  763.                      (scan-body-forms forms
  764.                               env
  765.                               new-defs
  766.                               cont))
  767.                     ((eq? new-defs defs)
  768.                      (cont defs
  769.                            (append exps forms)
  770.                            env))
  771.                     (else (body-lossage node env))))))
  772.           (else
  773.            (cont defs (cons node forms) env))))))
  774.  
  775. (define (body-lossage node env)
  776.   (syntax-error "definitions and expressions intermixed"
  777.         (schemify node env)))
  778.  
  779.  
  780. (define begin-node? (node-predicate 'begin syntax-type))
  781.  
  782. ; --------------------
  783. ; Variable types
  784.  
  785. (define (variable-type type)
  786.   (list 'variable type))
  787.  
  788. (define (variable-type? type)
  789.   (and (pair? type) (eq? (car type) 'variable)))
  790. (define variable-value-type cadr)
  791.  
  792. ; Used in two places:
  793. ; 1. GET-LOCATION checks to see if the context of use (either variable
  794. ;    reference or assignment) is compatible with the declared type.
  795. ; 2. CHECK-STRUCTURE checks to see if the reconstructed type is compatible
  796. ;    with any type declared in the interface.
  797.  
  798. (define (compatible-types? have-type want-type)
  799.   (if (variable-type? want-type)
  800.       (and (variable-type? have-type)
  801.        (same-type? (variable-value-type have-type)
  802.                (variable-value-type want-type)))
  803.       (meet? (if (variable-type? have-type)
  804.          (variable-value-type have-type)
  805.          have-type)
  806.          want-type)))
  807.  
  808.  
  809. ; Usual type for Scheme variables.
  810.  
  811. (define usual-variable-type (variable-type value-type))
  812.  
  813.  
  814. (define undeclared-type ':undeclared)    ;cf. really-export macro
  815.  
  816.  
  817. ; Associate a reader (parser) with an environment.
  818.  
  819. (define funny-name/reader (string->symbol ".reader."))
  820.  
  821. ;(define (set-package-reader! p reader)
  822. ;  (package-define-funny! p funny-name/reader reader))
  823.  
  824. (define (environment-reader env)
  825.   (or (get-funny env funny-name/reader) read))
  826.